using System;

using Peradigm.Framework.Domain.Parties;
using Peradigm.Framework.Domain.Parties.Exceptions;
using Peradigm.Framework.Persistence;

using Liberty.Domain.Kernel;
using Liberty.Domain.ServiceMemberManagement;

namespace Liberty.Domain.ApplicationManagement
{
    [Serializable]
    public class Applicant : Person
    {
        #region Constants
        public const string
            DESCRIPTOR_ADDRESS = TypeOfContactPoint.DESCRIPTOR_PRIMARY;
        #endregion

        #region Event Handlers
        #endregion

        #region Methods
        public static Applicant ApplicantFrom( ServiceMember serviceMember )
        {
            Applicant newApplicant = new Applicant( Applicant.NEW_OID, Applicant.NEW_VERSION, serviceMember.FirstName, serviceMember.LastName );
            return newApplicant;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="descriptor"></param>
        /// <returns></returns>
        public new Liberty.Domain.Kernel.Address AddressFor( string descriptor )
        {
            Liberty.Domain.Kernel.Address address = null;
            try
            {
                address = (Liberty.Domain.Kernel.Address) base.AddressFor( descriptor );
            }
            catch( ContactURINotFoundException )
            {
            }
            if( address == null )
            {
                address = new Liberty.Domain.Kernel.Address();
                this.AddAddress( descriptor, address );
            }
            return address;
        }

        public new PhoneNumber PhoneNumberFor( string descriptor )
        {
            PhoneNumber phoneNumber = null;
            try
            {
                phoneNumber = base.PhoneNumberFor( descriptor );
            }
            catch( ContactURINotFoundException )
            {
            }
            if( phoneNumber == null )
            {
                phoneNumber = new UnvalidatedPhoneNumber();
                this.AddPhoneNumber( descriptor, phoneNumber );
            }
            return phoneNumber;
        }

        public new EMailAddress EmailAddressFor( string descriptor )
        {
            EMailAddress email = null;
            try
            {
                email = base.EmailAddressFor( descriptor );
            }
            catch( ContactURINotFoundException )
            {
            }
            if( email == null )
            {
                email = new UnvalidatedEMailAddress();
                this.AddEmailAddress( descriptor, email );
            }
            return email;
        }

        public Relationship RelateTo( RelationshipType kinship, ServiceMember serviceMember )
        {
            return this.AddRelationship( new Relationship( kinship, serviceMember, this ) );
        }
        #endregion

        #region Properties
        public Liberty.Domain.Kernel.Address Address
        {
            get
            {
                return this.AddressFor( Applicant.DESCRIPTOR_ADDRESS );
            }
            set
            {
                this.AddAddress( Applicant.DESCRIPTOR_ADDRESS, value );
            }
        }

        public EMailAddress EmailAddress
        {
            get
            {
                return this.EmailAddressFor( TypeOfContactPoint.DESCRIPTOR_PRIMARY );
            }
            set
            {
                this.AddEmailAddress( TypeOfContactPoint.DESCRIPTOR_PRIMARY, value );
            }
        }

        public PhoneNumber PrimaryPhoneNumber
        {
            get
            {
                return this.PhoneNumberFor( TypeOfContactPoint.DESCRIPTOR_PRIMARY );
            }
            set
            {
                this.AddPhoneNumber( TypeOfContactPoint.DESCRIPTOR_PRIMARY, value );
            }
        }

        public PhoneNumber SecondaryPhoneNumber
        {
            get
            {
                return this.PhoneNumberFor( TypeOfContactPoint.DESCRIPTOR_SECONDARY );
            }
            set
            {
                this.AddPhoneNumber( TypeOfContactPoint.DESCRIPTOR_SECONDARY, value );
            }
        }
        #endregion

        #region Private Methods
        #endregion

        #region Private Properties
        #endregion

        #region Construction and Finalization
        /// <summary>
        /// Creates a stubbed applicant populated with frequently used primitives.  
        /// Other aggregated objects are not populated by this factory method.
        /// </summary>
        /// <returns></returns>
        public static Applicant TestInstance()
        {
            Applicant stub = new Applicant( 12L, PersistentModel.NEW_VERSION, "Thomas", "Stevens" );
            stub.Pedigree = "M.D.";
            stub.Title = "Chief Instructor";

            return stub;
        }

        /// <summary>
        /// Create a new Applicant with minimal information.
        /// </summary>
        /// <param name="oid"></param>
        /// <param name="version"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        public Applicant( long oid, byte[] version, string firstName, string lastName ) 
            : base( oid, version, firstName, lastName )
        {
        }

        /// <summary>
        /// Create a new applicant that is related to an existing Service Member.
        /// </summary>
        /// <param name="oid"></param>
        /// <param name="version"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <param name="kinship"></param>
        /// <param name="serviceMember"></param>
        public Applicant( long oid, byte[] version, string firstName, string lastName, RelationshipType kinship, ServiceMember serviceMember ) 
            : this( oid, version, firstName, lastName )
        {
            this.RelateTo( kinship, serviceMember );
        }
        #endregion

        #region Data Elements
        #endregion
        
    }
}
